package server;

import java.util.Vector;

import com.Constants;
import com.Event;
import com.LedsManager;
import com.sun.spot.interisolate.ReplyEnvelope;
import com.sun.spot.interisolate.RequestSender;
import com.sun.spot.resources.transducers.LEDColor;
import com.sun.squawk.io.mailboxes.NoSuchMailboxException;

import requestEnvelopes.agent.ReceiveEvent;
import server.interfaces.IDispatcher;
import server.interfaces.IMobileAgentExecutionEngine;

public class Dispatcher implements IDispatcher {
	
	private IMobileAgentExecutionEngine executionEngine = null;
	
	private Vector events = null;
	
	public Dispatcher (IMobileAgentExecutionEngine executionEngine) {
		
		this.executionEngine = executionEngine;
		this.events = new Vector();
	}
	
	public synchronized void send(Event event) {
		this.events.addElement(event);
		this.notifyAll();		
	}
	
	public void run() {
		while(true){
			waitForEventsToSend();
			try {
				
				while ( this.events.size() > 0 ) {

					Event event = (Event)this.events.firstElement();
					
					try {
						String target = event.getTargetID();
						if (target.equals(Constants.BROADCAST)) {
							Vector mobileAgentsName = this.executionEngine.getLocalAgentsID();
							for (int i = 0; i < mobileAgentsName.size(); i++) {
								if (!((String)mobileAgentsName.elementAt(i)).equals(event.getSourceID())) {
									RequestSender agent	= RequestSender.lookup((String)mobileAgentsName.elementAt(i));								
									ReplyEnvelope reply = agent.send(new ReceiveEvent(event));
									reply.checkForRuntimeException();
								}
							}
						}
						else {
							RequestSender agent	= RequestSender.lookup(target);								
							ReplyEnvelope reply = agent.send(new ReceiveEvent(event));
							reply.checkForRuntimeException();
						}
						
					}
					catch (NoSuchMailboxException e) {
						LedsManager.error();
						e.printStackTrace();
					}
					this.events.removeElementAt(0);

				}
				
			} catch (Exception e) {		
				LedsManager.error(LEDColor.YELLOW);
				e.printStackTrace();
			}
		} // while
	}

	/**
	 * This method waits for events to dispatch in the local node, by a "wait-notify" mechanism
	 */
	private synchronized void waitForEventsToSend() {
		while (this.events.size() == 0 ) {
			try {
				wait();
			}
			catch (InterruptedException e) {
				LedsManager.error(LEDColor.YELLOW);
				e.printStackTrace();
			}
		}
		
	}
	
}
